using GridExtend;
using MyEditor.ShapeEditor;
using Services;
using System.Collections.Generic;
using UnityEngine;

public class CharacterEye : MonoBehaviour
{
    private Character character;

    private readonly List<Vector2> eyesOffset = new List<Vector2>();
    private LayerMask obstacleLayer;
    private MyGrid MyGrid => ActionController.GlobalGrid;

    protected virtual void Awake()
    {
        character = GetComponentInParent<Character>();
        GenerateEyes();
        obstacleLayer = ServiceLocator.Get<ActionController>().obstacleLayer;
    }

    public List<Vector2> GetEyesPosition()
        => eyesOffset.AllAdd(transform.position.RemoveZ());

    private void GenerateEyes()
    {
        if (TryGetComponent(out PolygonEditor editor))
        {
            editor.GetLocalPoints(eyesOffset);
            Destroy(editor);
        }
    }

    public bool CanSee(Vector2Int target)
    {
        float v = character.data.view * character.data.view;
        return See(GetEyesPosition(), ActionController.GlobalGrid.CellToWorld(target), v);
    }
    public bool CanSee(List<Vector2Int> positions)
        => positions.TrueForAny(x => CanSee(x));
    public bool CanSee(Character targetCharacter)
    {
        if (targetCharacter == null)
            return false;
        if (targetCharacter == character)
            return true;
        float v = character.data.view * character.data.view * targetCharacter.data.visibility * targetCharacter.data.visibility;
        List<Vector2Int> occupy = targetCharacter.GetOccupyPositions();
        return MyGrid != null && occupy.TrueForAny(x => See(GetEyesPosition(), MyGrid.CellToWorld(x), v));
    }

    private bool See(List<Vector2> eyes, Vector2 worldPosition, float sqrDistance)
        => eyes.TrueForAny(
            x => (x - worldPosition).sqrMagnitude <= sqrDistance
            && !PhysicsTool2D.ObstructRaycast(x, worldPosition, obstacleLayer)
            );

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.blue;
        if (eyesOffset != null)
        {
            foreach (Vector2 point in GetEyesPosition())
            {
                Gizmos.DrawCube(point, 0.1f * Vector3.one);
            }
        }
    }
}
